/**
 * @method kxui 模块管理方法
 * @author Lkx
 *
 * @method use 模块加载(普通模组)
 * @method vue 模块加载(独占模块)
 * @method config 配置参数
 * @method info 信息查询
 */

(function (factory) {

  if ((typeof exports === 'object') && (typeof module !== 'undefined')) {
    window.Kxui = window.kxui = module.exports = factory();
  } else {
    window.Kxui = window.kxui = factory();
  }

}(function () {

  'use strict';

  let ownMod = ['method', 'countdown', 'drop', 'popup', 'verification', 'file'];
  let othersMod = ['moment'];
  let stockMod = ownMod.concat(othersMod);
  let isConfig = true;
  let modulesInfo = {
    name: 'kxui',
    info: 'Common Development Function Packaging',
    version: '1.6.11',
    createTime: '2018.05.31',
    updateTime: '2019.11.26'
  };

  /**
   * 逻辑入口
   * @method Load
   * @for Kxui
   * @param {object} parameter 配置参数
   */
  let Load = function (Kxui, parameter) {
    this.kxui = Kxui;
    this.parameter = parameter;
    this.module = (typeof this.parameter.module === 'string') ? [this.parameter.module] : (typeof this.parameter.module === 'object') ? this.parameter.module : false;
    this.callback = (typeof this.parameter.callback === 'function') ? this.parameter.callback : false;
    if (!this.module || !this.callback) {
      throws(1, this.kxui, 0);
    } else {
      this.definition();
    }
  };

  Load.prototype = {

    /**
     * 定义成员变量
     * @method definition
     * @for Load
     */
    definition: function () {
      this.loadLine = 0;
      this.wheelSearch = 0;
      this.domain = domain();
      ((typeof exports === 'object') && (typeof module !== 'undefined')) ? this.imports(): this.shunt();
    },

    /**
     * 模块加载分流(ES6模式)
     * @method imports
     * @for Load
     */
    imports: function () {
      require('./assets/css/kxui.css');
      for (let i = 0; i < this.module.length; i++) {
        if (!this.kxui[(this.module[i])] && stockMod.indexOf(this.module[i].toLowerCase()) >= 0) {
          let mod = require('./modules/' + this.module[i]);
          this.othersRegistered(this.module[i], mod);
        } else if (this.kxui[(this.module[i])]) {
          throws(0, this.kxui, 2, this.module[i]);
        } else {
          throws(0, this.kxui, 1, this.module[i]);
        }
      }
      this.end();
    },

    /**
     * 模块加载分流(传统模式)
     * @method shunt
     * @for Load
     */
    shunt: function () {
      this.style();
      if (stockMod.indexOf(this.module[this.loadLine].toLowerCase()) >= 0) {
        this.register(this.module[this.loadLine]);
      } else {
        throws(0, this.kxui, 1, this.module[this.loadLine]);
        this.loop();
      }
    },

    /**
     * 模块样式加载
     * @method style
     * @for shunt
     */
    style: function () {
      let head = document.querySelector('head');
      let link = document.createElement('link');
      link.media = 'all';
      link.type = 'text/css';
      link.rel = 'stylesheet';
      link.href = this.domain + 'assets/css/kxui.css';
      head.appendChild(link);
    },

    /**
     * 模块注册记录
     * @method register
     * @for shunt/loop
     * @param {string} mod 模块名称
     */
    register: function (mod) {
      if (!this.kxui[mod]) {
        this.create(mod);
      } else {
        throws(0, this.kxui, 2, mod);
        if (this.loadLine < this.module.length - 1) {
          this.loop();
        } else {
          this.end();
        }
      }
    },

    /**
     * 创建模块标签
     * @method create
     * @for register
     * @param {string} mod 模块名称
     */
    create: function (mod) {
      let that = this;
      let body = document.querySelector('body');
      let script = document.createElement('script');
      script.type = 'text/javascript';
      script.async = 'async';
      script.charset = 'utf-8';
      script.src = that.domain + 'modules/' + mod + '.js';
      if (body) {
        body.appendChild(script);
        that.wait(body, script, mod);
      } else if (that.wheelSearch < 10) {
        setTimeout(function () {
          that.wheelSearch = that.wheelSearch + 1;
          that.create(mod);
        });
      } else {
        throws(1, this.kxui, 3, mod);
      }
    },

    /**
     * 等待当前模块加载完毕
     * @method wait
     * @for create
     * @param {object} body 结构对象
     * @param {object} script 等待的标签对象
     * @param {string} mod 模块名称
     */
    wait: function (body, script, mod) {
      let that = this;
      if (script.readyState) {
        script.onreadystatechange = function () {
          if (script.readyState === 'complete' || script.readyState === 'loaded') {
            script.onreadystatechange = null;
            that.othersRegistered(mod);
            that.waitEnd(body, script);
          }
        };
      } else {
        script.onload = function () {
          that.othersRegistered(mod);
          that.waitEnd(body, script);
        };
      }
    },

    /**
     * 模块注册/第三方模块注册
     * @method othersRegistered
     * @for imports/wait
     * @param {string} mod 模块名称
     * @param {object} content 模块内容
     */
    othersRegistered: function (mod, content) {
      if (!this.kxui[mod]) {
        if (content) {
          this.kxui[mod] = content;
        } else if (window[mod]) {
          this.kxui[mod] = window[mod];
          delete window[mod];
        } else {
          throws(0, this.kxui, 1, mod);
        }
      }
    },

    /**
     * 当前模块加载完毕
     * @method waitEnd
     * @for wait
     * @param {object} body 结构对象
     * @param {object} script 等待的标签对象
     */
    waitEnd: function (body, script) {
      body.removeChild(script);
      this.loop();
    },

    /**
     * 加载环路
     * @method loop
     * @for shunt/wait/register/loop
     */
    loop: function () {
      this.loadLine = this.loadLine + 1;
      if (this.module[this.loadLine] && stockMod.indexOf(this.module[this.loadLine].toLowerCase()) >= 0) {
        this.register(this.module[this.loadLine]);
      } else if (this.loadLine < this.module.length - 1) {
        throws(0, this.kxui, 1, this.module[this.loadLine]);
        this.loop();
      } else {
        if (this.module[this.loadLine]) {
          throws(0, this.kxui, 1, this.module[this.loadLine]);
        }
        this.end();
      }
    },

    /**
     * 结尾方法
     * @method end
     * @for isModule/imports/shunt/register/Load
     */
    end: function () {
      this.callback(this.kxui.info());
    }
  };

  /**
   * 获取引入路径
   * @method domain
   * @for Load/Kxui
   * @return {string} 引入路径前缀
   */
  function domain() {
    let kxuiDomain = document.scripts;
    let last = kxuiDomain.length - 1;
    for (let i = last; i >= 0; i--) {
      let src = kxuiDomain[i].src.toLowerCase() || false;
      if (src && src.indexOf('kxui.js') >= 0) {
        kxuiDomain = kxuiDomain[i].src.substring(0, kxuiDomain[i].src.lastIndexOf('/') + 1);
        break;
      }
    }
    return kxuiDomain;
  }

  /**
   * 获取当前接入设备
   * @method getDevice
   * @for Kxui
   * @return {string} 当前的设备
   */
  function getDevice() {
    let device = 'pc';
    let ua = navigator.userAgent.toLowerCase();
    if (/iphone|ipad|ipod/.test(ua)) {
      device = 'ios';
    } else if (/android/.test(ua)) {
      device = 'android';
    }
    return device;
  }

  /**
   * 控制台错误/警告
   * @method warn
   * @for Load
   * @param {number} error 抛出错误的类型 0:警告 1:错误
   * @param {object} kxui 框架自身
   * @param {number} num 输入警告文案编号
   * @param {string} mod 发生错误的模块名称
   */
  function throws(error, kxui, num, mod) {
    if (kxui.configuration.debug) {
      let nums = {};
      nums[0] = '加载方法 {use} 不符合结构规范';
      nums[1] = '加载模块 {' + mod + '} 失败，未能找到此模块';
      nums[2] = '加载模块 {' + mod + '} 失败，勿重复加载';
      nums[3] = '加载模块 {' + mod + '} 失败，未能找到 {body} 节点';
      let text = 'Kxui-' + modulesInfo.version + '： ' + nums[num] + '，请检查修改。';
      error === 1 ? console.error(text) : console.warn(text);
    }
  }

  /**
   * 方法的主入口
   * @method Kxui
   * 开发常用操作方法，可根据需要加载不同的模块，提高开发效率
   */
  let Kxui = function () {
    this.about = modulesInfo;
  };

  /**
   * 模块加载(普通模组)
   * @method use
   * @for Kxui
   * @param {string/array} mod 模块名称
   * @param {function} callback 加载完成回调方法
   */
  Kxui.prototype.use = function (mod, callback) {
    let data = {};
    data.module = mod;
    data.callback = callback;
    this.config('use');
    new Load(this, data);
  };

  /**
   * 模块加载(独占模块)
   * @method use
   * @for Kxui
   */
  Kxui.prototype.vue = function () {
    let vue = {
      install: function (Vue) {
        Vue.component('kxui-popup', require('./modules.vue/popup.js').default);
      }
    };
    return vue;
  };

  /**
   * 配置参数
   * @method use
   * @for Kxui
   * @param {object} parameter 配置参数
   */
  Kxui.prototype.config = function (parameter) {
    if (isConfig) {
      isConfig = (parameter === 'use');
      parameter = (typeof parameter === 'object' ? parameter : {});
      this.configuration = {
        debug: (typeof parameter.debug === 'boolean' ? parameter.debug : true)
      };
    }
  };

  /**
   * 信息返回
   * @method info
   * @for Kxui
   * @return {object} 开发信息
   */
  Kxui.prototype.info = function () {
    return {
      'device': getDevice(),
      'about': modulesInfo,
      'address': {
        'host': window.location.host,
        'hostName': window.location.hostname,
        'href': window.location.href,
        'origin': window.location.protocol + '//' + window.location.host,
        'pathName': window.location.pathname,
        'port': window.location.port,
        'protocol': window.location.protocol
      },
      'size': {
        'cDocW': document.documentElement.clientWidth,
        'cDocH': document.documentElement.clientHeight,
        'tDocW': window.top.document.documentElement.clientWidth,
        'tDocH': window.top.document.documentElement.clientHeight
      },
      'document': {
        'c': document,
        't': window.top.document
      }
    };
  };

  return new Kxui();

}));